home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1995 #5 & #6
/
Amiga Plus CD - 1995 - No. 5 and 6.iso
/
pd
/
datatypes
/
bmp
/
source
/
getbmp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-11
|
8KB
|
364 lines
/*
** our include
*/
#include "getbmp.h"
/*
** easy access of a char-array as a "structure" (IJG sources v5.0b)
*/
#define UCH(x) \
((int) (x))
#define GET_2B(array,offset) \
((unsigned int) UCH(array[offset]) + \
(((unsigned int) UCH(array[offset+1])) << 8))
#define GET_4B(array,offset) \
((ULONG) UCH(array[offset]) + \
(((ULONG) UCH(array[offset+1])) << 8) + \
(((ULONG) UCH(array[offset+2])) << 16) + \
(((ULONG) UCH(array[offset+3])) << 24))
/*
** get dt attribute(s)
*/
ULONG set_dt_attrs(Object *obj, ULONG data, ...)
{
return (SetDTAttrsA(obj,NULL,NULL,(struct TagItem *)&data));
}
/*
** get dt attribute(s)
*/
ULONG get_dt_attrs(Object *obj, ULONG data, ...)
{
return (GetDTAttrsA(obj,(struct TagItem *)&data));
}
/*
** expand every bit to a byte
*/
VOID convert_1bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
{
UBYTE *p=outbuf,c;
int i,j;
for(i=width/8; i>0; i--)
{
for(c=*pixelbuf++,j=7; j>=0; j--)
{
*p++ = ((c & 0x80) ? 1 : 0);
c <<= 1;
}
}
if ((i=width%8))
{
for(c=*pixelbuf,j=7; i>0; j--,i--)
{
*p++ = ((c & 0x80) ? 1 : 0);
c <<= 1;
}
}
}
/*
** expand every 4 bits to a byte
*/
VOID convert_4bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
{
UBYTE *p=outbuf,c;
int i;
for(i=width/2; i>0; i--)
{
c = *pixelbuf++;
*p++ = (c >> 4); /* ((c & 0xf0) >> 4); */
*p++ = (c & 0xf);
}
if (width & 1)
{
c = *pixelbuf; *p = (c >> 4); /* ((c & 0xf0) >> 4); */
}
}
/*
** perform a simple copy (outbuf is WritePixelLine8() aware..)
*/
VOID convert_8bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
{
CopyMem(pixelbuf,outbuf,width);
}
/*
** create the bitmap
*/
int decode_bmp_picture(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd, ULONG title)
{
register VOID (*convert)(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width) REG(a3);
struct BitMap *tbm,*bm;
struct RastPort trp,rp;
UBYTE *albuff,*buffer,*p;
ULONG modeid,padwidth,width,height,depth,large;
int line,index,success=FALSE;
width = bmhd->bmh_Width; height = bmhd->bmh_Height; depth = bmhd->bmh_Depth;
if ((bm=AllocBitMap(width,height,depth,BMF_CLEAR|BMF_DISPLAYABLE,NULL)) != NULL)
{
InitRastPort(&rp); rp.BitMap = bm;
if ((tbm=AllocBitMap(width,1,depth,BMF_CLEAR,NULL)) != NULL)
{
InitRastPort(&trp); trp.BitMap = tbm;
if ((albuff=AllocPooled(pool,((width+15)&~15))) != NULL)
{
padwidth = ((((width * depth) + 31) & ~31) / 8);
large = padwidth * height;
if ((buffer=AllocPooled(pool,large)) != NULL)
{
if (Read(fh,buffer,large) != large)
{
buffer=NULL;
}
}
else
{
buffer=AllocPooled(pool,padwidth); large=0;
}
if (buffer != NULL)
{
convert = convert_1bit;
if (depth != 1)
{
convert = convert_4bit;
if (depth != 4)
convert = convert_8bit;
}
for (line=(height-1),index=0; line>=0; index++,line--)
{
if (large)
p=&buffer[index*padwidth];
else
if (Read(fh,(p=buffer),padwidth) != padwidth)
goto error;
(*convert)(p,albuff,width);
WritePixelLine8(&rp,0,line,width,albuff,&trp);
}
modeid = LORES_KEY;
if ((UWORD)width >= 640)
modeid = HIRES;
if ((UWORD)height >= 400)
modeid |= LACE;
set_dt_attrs(obj,
DTA_ObjName, title,
DTA_NominalHoriz, width,
DTA_NominalVert, height,
PDTA_BitMap, bm,
PDTA_ModeID, modeid,
TAG_DONE);
success = TRUE;
}
}
error:
FreeBitMap(tbm);
}
if (!success)
FreeBitMap(bm);
}
return success;
}
/*
** extract all required information from the bmp header
*/
int read_bmp_header(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd)
{
UBYTE bmpfileheader[14+64],*coltab,*cmap;
#define bmpinfoheader (bmpfileheader+14)
LONG *cregs;
LONG biCompression;
LONG biClrUsed;
LONG biPlanes;
LONG bfOffBits;
LONG headerSize;
LONG bPad;
LONG cmapentrysize;
LONG coltabsize;
int i;
if (Read(fh,bmpfileheader,18) != 18)
return FALSE;
if (((UWORD)GET_2B(bmpfileheader,0)) != 0x4D42)
return FALSE;
bfOffBits = (LONG) GET_4B(bmpfileheader,10);
headerSize = (LONG) GET_4B(bmpinfoheader, 0);
if (headerSize < 12 || headerSize > 64)
return FALSE;
if (Read(fh,bmpinfoheader+4,headerSize-4) != (headerSize-4))
return FALSE;
switch(headerSize)
{
case 12: /* OS/2 1.x */
bmhd->bmh_Width = (WORD) GET_2B(bmpinfoheader, 4);
bmhd->bmh_Height = (WORD) GET_2B(bmpinfoheader, 6);
biPlanes = GET_2B(bmpinfoheader, 8);
bmhd->bmh_Depth = (WORD) GET_2B(bmpinfoheader,10);
biCompression = 0;
biClrUsed = 0;
switch (bmhd->bmh_Depth)
{
case 1:
case 4:
case 8:
cmapentrysize = 3;
break;
case 24:
cmapentrysize = 0;
break;
default:
cmapentrysize = 0;
break;
}
break;
case 40: /* Windows 3.x or OS/2 2.x */
case 64:
bmhd->bmh_Width = (WORD) GET_4B(bmpinfoheader, 4);
bmhd->bmh_Height = (WORD) GET_4B(bmpinfoheader, 8);
biPlanes = GET_2B(bmpinfoheader,12);
bmhd->bmh_Depth = (WORD) GET_2B(bmpinfoheader,14);
biCompression = GET_4B(bmpinfoheader,16);
biClrUsed = GET_4B(bmpinfoheader,32);
switch (bmhd->bmh_Depth)
{
case 1:
case 4:
case 8:
cmapentrysize = 4;
break;
case 24:
cmapentrysize = 0;
break;
default:
cmapentrysize = 0;
break;
}
break;
default:
cmapentrysize = 0;
break;
}
bmhd->bmh_PageWidth = bmhd->bmh_Width;
bmhd->bmh_PageHeight = bmhd->bmh_Height;
if (biPlanes != 1 || biCompression != 0 || cmapentrysize == 0)
return FALSE;
if (biClrUsed <= 0)
biClrUsed = 1L << bmhd->bmh_Depth;
if (biClrUsed > 256)
return FALSE;
(void)set_dt_attrs(obj, PDTA_NumColors,(ULONG)biClrUsed, TAG_DONE);
if ((get_dt_attrs(obj, PDTA_ColorRegisters,(ULONG)&cmap,PDTA_CRegs,(ULONG)&cregs, TAG_DONE)) != 2)
return FALSE;
coltabsize = biClrUsed * cmapentrysize;
if ((coltab=AllocPooled(pool,coltabsize)) == NULL)
return FALSE;
if (Read(fh,coltab,coltabsize) != coltabsize)
return FALSE;
/*
** do not use "struct ColorRegister" for cmap since with the amiga port
** of gcc a sizeof() for this structure is four and not three.. oh well
*/
for(i=0; i<biClrUsed; cmap+=3,cregs+=3,coltab+=cmapentrysize,i++)
{
UBYTE r,g,b;
r = coltab[2];
cmap[0] = r; cregs[0] = r << 24;
g = coltab[1];
cmap[1] = g; cregs[1] = g << 24;
b = coltab[0];
cmap[2] = b; cregs[2] = b << 24;
}
bPad = bfOffBits - (14 + headerSize + coltabsize);
for(;bPad>0;)
{
LONG size = (bPad < sizeof(bmpfileheader) ? bPad : sizeof(bmpfileheader));
if (Read(fh,&bmpfileheader[0],size) != size)
break;
bPad -= size;
}
return (bPad == 0 ? TRUE : FALSE);
}
/*
** load the picture
*/
int GetBMP(Class *cl, Object *obj, struct TagItem *attrs)
{
struct BitMapHeader *bmhd;
LONG ioerr;
APTR pool;
BPTR fh;
int success=FALSE;
if ((pool=CreatePool(MEMF_ANY,1024,1024)) != NULL)
{
if ((get_dt_attrs(obj, DTA_Handle,&fh,PDTA_BitMapHeader,&bmhd, TAG_DONE) == 2) && fh)
for(;;)
{
ioerr=ERROR_OBJECT_WRONG_TYPE;
if ((success=read_bmp_header(obj,pool,fh,bmhd)) != FALSE)
{
if ((success=decode_bmp_picture(obj,pool,fh,bmhd,GetTagData(DTA_Name,NULL,attrs))) != FALSE)
break;
ioerr=ERROR_NO_FREE_STORE;
}
SetIoErr(ioerr); break;
}
DeletePool(pool);
}
return success;
}